home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / formats / ps16form.lzh / MODLOAD.ASM < prev    next >
Assembly Source File  |  1993-04-26  |  20KB  |  489 lines

  1. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  2. struc   SampleRec
  3. sname           db      16h dup (?)
  4. length          dw      ?
  5. volume          dw      ?
  6. repeat          dw      ?
  7. replen          dw      ?
  8. ends    SampleRec
  9.  
  10. struc   Header
  11. songname        db      20 dup (?)
  12. samples         db      31*size SampleRec dup (?)
  13. songlen         db      ?
  14. restart         db      ?
  15. sequences       db      128 dup (?)
  16. mk              dd      ?
  17. ends    Header
  18.  
  19. ModHeader       dw      0       ;; Segment of MOD Header
  20. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  21.  
  22. SigCopy         db      'PS16■'
  23. PS16            PS16Header <>
  24. HeaderSeg       dw      0
  25.  
  26. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  27. ; MOD_Open - MOD conversion routine.  Assumes you know the file is a .MOD.
  28. ;   In : CX:DX - Input MOD filename.
  29. ;        BX:SI - Output PS16 filename.
  30. ;        AX    - Memory segment(s) to do conversion (at least 64k).
  31. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  32. ModIn           dw      0       ;; MOD input handle.
  33. ModOut          dw      0       ;; PS16 output handle.
  34. ModTOD          dw      0       ;; Top of data.
  35. proc            MOD_Convert near
  36.                 push    ds es
  37.                 mov     [cs:ModTOD],ax
  38.                 ; ▒▒▒▒▒ Open/create files.
  39.                 mov     ds,cx           ;; Open input MOD.
  40.                 mov     ax,3D00h
  41.                 int     21h
  42.                 jb      @@Exit
  43.                 mov     [cs:ModIn],ax
  44.                 mov     ds,bx           ;; Create output PS16.
  45.                 mov     dx,si
  46.                 mov     cx,0
  47.                 mov     ah,3Ch
  48.                 int     21h
  49.                 mov     [cs:ModOut],ax
  50.  
  51.                 ; ▒▒▒▒▒ Read and convert module.
  52.                 mov     ax,cs
  53.                 mov     ds,ax
  54.                 mov     es,ax
  55.                 call    MOD_ReadConvert
  56.  
  57.                 ; ▒▒▒▒▒ Close files.
  58.                 mov     ah,3Eh          ;; Close module
  59.                 mov     bx,[cs:ModIn]
  60.                 int     21h
  61.                 mov     ah,3Eh          ;; Close PS16
  62.                 mov     bx,[cs:ModOut]
  63.                 int     21h
  64. @@Exit:         pop     es ds
  65.                 ret
  66. endp            MOD_Convert
  67.  
  68. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  69. ; MOD_ReadConvert - Conversion routine.  Must be called by MOD_Open.
  70. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  71. proc            MOD_ReadConvert near
  72.                 ; ▒▒▒▒▒ Read module header.
  73.                 mov     ax,[cs:ModTOD]
  74.                 mov     [cs:HeaderSeg],ax
  75.                 add     [cs:ModTOD],size Header/16+1
  76.                 mov     ds,ax
  77.                 mov     es,ax
  78.                 mov     ax,3F00h
  79.                 mov     bx,[cs:ModIn]
  80.                 xor     dx,dx
  81.                 mov     cx,size Header
  82.                 int     21h
  83.  
  84.                 ; ▒▒▒▒▒ Test for 15 or 31 instrument module.
  85.                 cmp     [Word ds:Header.mk],'.M'
  86.                 jnz     @@CheckFLT4
  87.                 cmp     [Word ds:2+Header.mk],'.K'
  88.                 jz      @@31Ins
  89. @@CheckFLT4:    cmp     [Word ds:Header.mk],'LF'
  90.                 jnz     @@15Ins
  91.                 cmp     [Word ds:2+Header.mk],'4T'
  92.                 jz      @@31Ins
  93.  
  94. @@15Ins:        ; ▒▒▒▒▒ Do 15 instrument conversion to 31 instrument.
  95.                 mov     si,20+15*30                ;; Copy orders, etc.
  96.                 mov     di,(offset (Header).songlen)
  97.                 mov     cx,134
  98.                 rep     movsb
  99.                 mov     di,offset Header+20+15*30  ;; Clear out 16-31 ins.
  100.                 mov     cx,16*30
  101.                 mov     al,0
  102.                 rep     stosb
  103.                 mov     ax,4200h                   ;; Reposition file ptr.
  104.                 mov     bx,[cs:ModIn]
  105.                 mov     cx,0
  106.                 mov     dx,258h
  107.                 int     21h
  108.  
  109. @@31Ins:        ; ▒▒▒▒▒ Convert 31 instrument header to PS16.
  110.                 call    MOD_ConvertHeader
  111.  
  112.                 ; ▒▒▒▒▒ Convert all patterns to PS16 format.
  113.                 call    MOD_LoadSavePatterns
  114.  
  115.                 ; ▒▒▒▒▒ Convert all samples to PS16 format.
  116.                 call    MOD_LoadSaveSamples
  117.  
  118.                 ; ▒▒▒▒▒ Convert all instrument names to PS16 format.
  119.                 call    MOD_ConvertComments
  120.  
  121.                 ; ▒▒▒▒▒ Write final header out.
  122.                 mov     ax,4200h
  123.                 mov     bx,[cs:ModOut]
  124.                 mov     cx,0
  125.                 mov     dx,0
  126.                 int     21h
  127.                 mov     ax,cs
  128.                 mov     ds,ax
  129.                 mov     cx,size PS16Header
  130.                 mov     dx,offset PS16
  131.                 mov     ah,40h
  132.                 int     21h
  133.  
  134.                 ret
  135. endp            MOD_ReadConvert
  136.  
  137. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  138. ; MOD_ConvertHeader - Converts the module header to a PS16 header.  Called
  139. ;                     from MOD_ReadConvert.
  140. ;   In : DS - set to segment of module header.
  141. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  142. proc            MOD_ConvertHeader near
  143.                 pusha
  144.                 push    ds
  145.  
  146.                 ; ▒▒▒▒▒ Clear out PS16 Header Data.
  147.                 mov     ax,cs
  148.                 mov     es,ax
  149.                 mov     di,offset PS16
  150.                 mov     al,0
  151.                 mov     cx,size PS16Header
  152.                 rep     stosb
  153.  
  154.                 ; ▒▒▒▒▒ Copy Sig and Name to PS16 Header.
  155.                 mov     di,offset PS16
  156.                 mov     ax,[Word cs:SigCopy]
  157.                 stosw
  158.                 mov     ax,[Word cs:SigCopy+2]
  159.                 stosw
  160.                 mov     al,[Byte cs:SigCopy+4]
  161.                 stosb
  162.                 mov     si,(offset (Header).songname)
  163.                 mov     di,offset PS16.SongName
  164.                 mov     cx,20
  165.                 rep     movsb
  166.                 mov     al,26           ;; ^Z terminate it.
  167.                 stosb
  168.  
  169.                 ; ▒▒▒▒▒ Copy Song Length and Sequences to PS16Header.
  170.                 mov     al,[ds:Header.songlen]
  171.                 mov     [es:PS16.SongLen],al
  172.                 mov     si,(offset (Header).sequences)
  173.                 mov     di,offset PS16.Sequences
  174.                 mov     cx,128
  175.                 xor     ax,ax
  176. @@SetBlock:     mov     ah,al
  177.                 jmp     @@BotLoop
  178. @@SearchLoop:   lodsb
  179.                 stosb
  180.                 cmp     al,ah
  181.                 jg      @@SetBlock
  182. @@BotLoop:      loop    @@SearchLoop
  183.                 mov     al,ah
  184.                 inc     al
  185.                 mov     [es:PS16.numpatterns],al
  186.  
  187.                 ; ▒▒▒▒▒ Copy Samples to PS16Header doing any appropriate
  188.                 ; ▒▒▒▒▒ fixups as necessary.
  189.                 mov     bp,31           ;; 31 instruments.
  190.                 mov     si,(offset (Header).samples)+(offset (SampleRec).length)
  191.                 mov     di,offset PS16.Samples
  192. @@FlipLoop:     mov     ax,[ds:si+4]    ;; Get repeat start.
  193.                 xchg    ah,al           ;; Amiga swap.
  194.                 mov     cx,ax           ;; Save.
  195.                 mov     bx,[ds:si+6]    ;; Get repeat length.
  196.                 xchg    bh,bl           ;; Amiga swap.
  197.                 add     ax,bx           ;; Add onto repeat.
  198.                 mov     dx,[ds:si]      ;; Get the length.
  199.                 xchg    dh,dl           ;; Amiga swap.
  200.                 cmp     ax,dx           ;; If the repeat+replen > length...
  201.                 jbe     @@OKRepeat
  202.                 shr     cx,1            ;; Then divide the repeat by 2.
  203. @@OKRepeat:     shl     dx,1            ;; Multiply the length by 2.
  204.                 mov     [Word es:di+PS16Sample.length],dx  ;; Store it.
  205.                 mov     ax,[ds:si+2]    ;; Get the volume and finetune and
  206.                 xchg    ah,al           ;; swap.
  207.                 mov     [Word es:di+PS16Sample.volume],ax  ;; Store.
  208.                 shl     bx,1            ;; Multiply the rep len by 2.
  209.                 cmp     bx,2            ;; If the repeat is <= 2,
  210.                 ja      @@StoreIt
  211.                 mov     bx,0            ;; then there isn't one.
  212. @@StoreIt:
  213.                 mov     [Word es:di+PS16Sample.replen],bx  ;; Store it.
  214.                 shl     cx,1            ;; Multiply the repeat by 2.
  215.                 mov     [Word es:di+PS16Sample.repeat],cx  ;; Store it.
  216.                 mov     [Word es:di+PS16Sample.c2freq],8448 ;; C-2 Frequency.
  217. @@OKSample:     add     si,size SampleRec ;; Go to next MOD sample.
  218.                 add     di,size PS16Sample ;; Go to next PS16 sample.
  219.                 dec     bp              ;; T minus bp samples.
  220.                 jne     @@FlipLoop      ;; Continue if not done.
  221.  
  222.                 ; ▒▒▒▒▒ Write PS16 Header to file.
  223.                 mov     bx,[cs:ModOut]
  224.                 mov     ax,cs
  225.                 mov     ds,ax
  226.                 mov     cx,size PS16Header
  227.                 mov     dx,offset PS16
  228.                 mov     ah,40h
  229.                 int     21h
  230.  
  231.                 pop     ds
  232.                 popa
  233.                 ret
  234. endp            MOD_ConvertHeader
  235.  
  236. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  237. ; MOD_LoadSavePatterns - Converts MOD patterns to PS16 patterns and saves
  238. ;                        them to disk.
  239. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  240. ModPatSeg       dw      0
  241. ModBuf3         dw      0
  242. LastLine        db      0FFh
  243. proc            MOD_LoadSavePatterns near
  244.                 ; ▒▒▒▒▒ Allocate buffers.
  245.                 mov     ax,[cs:ModTOD]
  246.                 mov     [cs:ModPatSeg],ax       ;; 1k MOD pattern buffer.
  247.                 add     ax,1024/16
  248.                 mov     [cs:ModBuf3],ax         ;; 3K PS16 pattern buffer.
  249.                 mov     es,ax
  250.  
  251.                 mov     [cs:LastLine],0FFh
  252.  
  253.                 ; ▒▒▒▒▒ Start loop.
  254.                 mov     cx,0
  255.  
  256. @@BlockReadLoop:; ▒▒▒▒▒ Read in a pattern.
  257.                 push    cx
  258.                 mov     cx,1024
  259.                 mov     bx,[cs:ModIn]
  260.                 mov     ax,[cs:ModPatSeg]
  261.                 mov     ds,ax
  262.                 xor     dx,dx
  263.                 mov     ax,3F00h                ; Load in the block.
  264.                 int     21h
  265.  
  266.                 ; ▒▒▒▒▒ Set up for compression.
  267.                 mov     ax,[cs:ModBuf3] ; Clear pattern of garbage.
  268.                 mov     es,ax
  269.                 mov     di,0
  270.                 mov     cx,3072/2
  271.                 mov     ax,0
  272.                 rep     stosw
  273.                 mov     di,0
  274.                 mov     ax,0            ; Size of pattern so far.
  275.                 stosw
  276.                 mov     al,64           ; Number of lines in pattern.
  277.                 stosb
  278.  
  279.                 mov     cx,0                    ; CX - Number of Channels Done.
  280. @@ChannelLoop:  ; ▒▒▒▒▒ Compress this baby!
  281.                 push    cx              ; Push Number of Channels Done.
  282.                 shl     cx,2            ; MOD channel offset - Channel*4.
  283.                 mov     si,cx
  284.                 mov     cx,0            ; Current line counter (0-63)
  285. @@LineLoop:     push    cx              
  286.                 cmp     [Word ds:si],0  ; Is there anything at all to
  287.                 jne     @@ItsThere      ;   compress?
  288.                 cmp     [Word ds:si+2],0
  289.                 je      @@NothingSkip   ; No!  Skip compressing this line.
  290. @@ItsThere:     xor     dh,dh
  291.                 mov     dl,cl
  292.                 dec     dl
  293.                 cmp     [cs:LastLine],dl
  294.                 jne     @@WholeLineStore
  295.                 mov     dh,10000000b
  296.                 jmp     @@SkipLineStore
  297. @@WholeLineStore:
  298.                 mov     al,cl           ; Store down the current line.
  299.                 stosb
  300. @@SkipLineStore:mov     [cs:LastLine],cl
  301.                 call    MOD_NoteMatcher ; Find a matching note.
  302.                 mov     bl,[ds:si]      ; Get the hi byte of instrument.
  303.                 and     bl,0F0h
  304.                 shl     bl,2            ; Shift it so it will fit in our note.
  305.                 or      al,bl           ; Put 'em together.
  306.                 or      al,dh           ; Put on whether line is continuous.
  307.                 stosb                   ;   ...and store it down.
  308.                 mov     ax,[ds:si+2]    ; Also store the lo byte of ins.
  309.                 stosw                   ;   and the special effect and data.
  310. @@NothingSkip:  add     si,16           ; Go to next MOD pattern line.
  311.                 pop     cx              ; Pop off the line counter.
  312.                 inc     cx
  313.                 cmp     cx,64           ; Are we done?
  314.                 jne     @@LineLoop
  315.                 mov     al,-1           ; Store a -1 to signify End of Track.
  316.                 stosb
  317.                 pop     cx              ; Pop off the Channel Counter.
  318.                 inc     cx              ; Since MODs are only four channels,
  319.                 cmp     cx,4            ;   we only have four channels to
  320.                 jnz     @@ChannelLoop   ;   do.
  321.  
  322.                 ; ▒▒▒▒▒ Store channels 4-16 as -1's.
  323.                 mov     cx,4            ; Channel Counter.
  324. @@CLoop:        mov     al,-1
  325.                 stosb
  326.                 inc     cx
  327.                 cmp     cx,16
  328.                 jnz     @@CLoop
  329.  
  330.                 ; ▒▒▒▒▒ Store the new PS16 pattern size in position 0.
  331.                 mov     bx,di           ; Save size.
  332.                 mov     cx,bx           ; Modify it to 16-byte bound.
  333.                 and     cx,0Fh          ; Are lower 4 bits set to anything?
  334.                 or      cx,cx
  335.                 je      @@OKSize
  336.                 and     bx,0FFF0h
  337.                 add     bx,16
  338. @@OKSize:       add     [Word cs:PS16.totalPatternSize],bx
  339.                 adc     [Word cs:2+PS16.totalPatternSize],0
  340.                 mov     di,0
  341.                 mov     cx,bx           ; Size for save.
  342.                 mov     ax,bx
  343.                 stosw
  344.  
  345.                 ; ▒▒▒▒▒ Write the PS16 pattern to disk.
  346.                 mov     ax,[cs:ModBuf3]
  347.                 mov     ds,ax
  348.                 mov     dx,0
  349.                 mov     bx,[cs:ModOut]
  350.                 mov     ah,40h
  351.                 int     21h
  352.  
  353.                 ; ▒▒▒▒▒ Are we done yet?
  354.                 pop     cx
  355.                 inc     cx
  356.                 cmp     cl,[cs:PS16.numpatterns]
  357.                 jnz     @@BlockReadLoop
  358.  
  359.                 ret
  360. endp            MOD_LoadSavePatterns
  361.  
  362. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  363. ; MOD_NoteMatcher - Tries to come up with an equivalent note position as per
  364. ;                   the MOD_Match table.  For instance, 1712 is 1, 56 is 60
  365. ;                   and 0 is 0.
  366. ;   In : DS:SI - MOD note.
  367. ;   Out: AX    - Note found (0-61)
  368. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  369. MOD_Match       dw      1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,912
  370.         dw    856,808,762,720,678,640,604,570,538,508,480,453
  371.         dw    428,404,381,360,339,320,302,285,269,254,240,226
  372.         dw    214,202,190,180,170,160,151,143,135,127,120,113
  373.         dw    107,101,95,90,85,80,75,71,67,63,60,56,0
  374. proc            MOD_NoteMatcher near
  375.                 mov     ax,[ds:si]      ; Get the note.
  376.                 xchg    ah,al           ; Amiga swap.
  377.                 and     ax,0FFFh        ; We want only the note.
  378.                 or      ax,ax           ; Is there one?
  379.                 je      @@Done          ;   NOPE!!!
  380.                 mov     bx,offset MOD_Match
  381.                 mov     cx,0            ; Note counter.
  382. @@NoteMatcher:  cmp     ax,[cs:bx]      ; Do we have a close match?
  383.                 jae     @@Found         ;   YES!
  384.                 add     bx,2            ; Kick our pointer up by a word.
  385.                 inc     cx              ; Increment the note counter.
  386.                 cmp     cx,61           ; Are we out of notes?
  387.         jnz    @@NoteMatcher
  388.                 mov     ax,0            ; If we made it here, then the note
  389.                 ret                     ; in question was WAY out of range.
  390. @@Found:        mov     ax,cx           ; Return the result.
  391.         inc    ax
  392. @@Done:         ret
  393. endp            MOD_NoteMatcher
  394.  
  395. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  396. ; MOD_LoadSaveSamples - Loads and saves the new PS16 samples to disk.
  397. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  398. proc            MOD_LoadSaveSamples near
  399.                 mov     cx,31
  400.                 mov     bx,offset PS16.Samples
  401. @@DoSamples:    push    cx bx
  402.  
  403.                 ; ▒▒▒▒▒ Is this a sample?
  404.                 mov     cx,[Word cs:bx+PS16Sample.length]
  405.                 or      cx,cx
  406.                 je      @@Bottom
  407.  
  408.                 ; ▒▒▒▒▒ Load sample.
  409.                 mov     ds,[cs:ModTOD]
  410.                 mov     dx,0
  411.                 mov     bx,[cs:ModIn]
  412.                 mov     ax,3F00h
  413.                 int     21h
  414.  
  415.                 ; ▒▒▒▒▒ Convert sample.
  416.                 mov     es,[cs:ModTOD]
  417.                 xor     si,si
  418.                 xor     di,di
  419.                 call    MOD_ConvertSample
  420.  
  421.                 ; ▒▒▒▒▒ Save sample.
  422.                 mov     ds,[cs:ModTOD]
  423.                 mov     dx,0
  424.                 mov     bx,[cs:ModOut]
  425.                 mov     ah,40h
  426.                 int     21h
  427.  
  428. @@Bottom:       pop     bx
  429.                 add     bx,size PS16Sample
  430.                 pop     cx
  431.                 loop    @@DoSamples
  432.                 ret
  433. endp            MOD_LoadSaveSamples
  434.  
  435. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  436. ; MOD_ConvertSample - Converts sample to new format for better compression.
  437. ;   In : DS:SI - Pointer to input sample
  438. ;        ES:DI - Pointer to output sample
  439. ;        CX    - Number of bytes to do.
  440. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  441. proc            MOD_ConvertSample
  442.                 push    cx
  443.                 jcxz    @@20            ; Abort if nothing to do.
  444.                 mov     ah, 0
  445. @@10:           lodsb
  446.                 mov     bl, al
  447.                 sub     al, ah
  448.                 stosb
  449.                 mov     ah, bl
  450.                 loop    @@10
  451. @@20:           pop     cx
  452.                 ret
  453. endp            MOD_ConvertSample
  454.  
  455. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  456. ; MOD_ConvertComments - Converts instrument names to comments.
  457. ;   In : DS:SI - Pointer to input sample
  458. ;        ES:DI - Pointer to output sample
  459. ;        CX    - Number of bytes to do.
  460. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  461. InsText         db      'INST',22,31
  462. proc            MOD_ConvertComments
  463.                 mov     ax,4201h        ; Get current position.
  464.                 mov     bx,[cs:ModOut]
  465.                 xor     cx,cx
  466.                 xor     dx,dx
  467.                 int     21h
  468.                 mov     [Word PS16.commentofs],ax       ; Store comment ofs.
  469.                 mov     [Word 2+PS16.commentofs],dx
  470.                 mov     ax,cs           ; Write INST text.
  471.                 mov     ds,ax
  472.                 mov     dx,offset InsText
  473.                 mov     cx,6
  474.                 mov     ah,40h
  475.                 int     21h
  476.                 mov     ds,[cs:HeaderSeg]
  477.                 mov     si,(offset (Header).samples)+(offset (SampleRec).sname)
  478.                 mov     cx,31
  479. @@CopyIns:      push    cx
  480.                 mov     dx,si           ; Write sample name.
  481.                 mov     cx,22
  482.                 mov     ah,40h
  483.                 int     21h
  484.                 add     si,size SampleRec
  485.                 pop     cx
  486.                 loop    @@CopyIns
  487.                 ret
  488. endp            MOD_ConvertComments
  489.